package nio.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 *  聊天室的服务端
 */
public class NioTestStart {

    private final static Map<String, SocketChannel> clientMap = new HashMap<>();

    public static void main(String[] args) throws IOException {

        Selector selector = Selector.open();
        ServerSocketChannel server = ServerSocketChannel.open();

        server.configureBlocking(false);

        server.bind(new InetSocketAddress(9000));

        server.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("监听端口： "+ 9000);


        while (true) {
            int numbers = selector.select();
            System.out.println("numbers： " + numbers);

            Set<SelectionKey> selectionKeys = selector.selectedKeys();

            System.out.println("selectionKeys " + selectionKeys);

            Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
            while (selectionKeyIterator.hasNext()) {
                SelectionKey selectionKey = selectionKeyIterator.next();
                final SocketChannel socketChannel;
                if (selectionKey.isAcceptable()) {
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
                    socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    // 相当于CallBack回去然后再进来一次循环进行下一次操作 多路复用
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    clientMap.put(UUID.randomUUID().toString(), socketChannel);
                    selectionKeyIterator.remove();
                }else if (selectionKey.isReadable()) {
                    socketChannel = (SocketChannel)selectionKey.channel();

                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    byteBuffer.clear();
                    int count = socketChannel.read(byteBuffer);
                    if (count > 0) {
                        byteBuffer.flip();
                        Charset charset = Charset.forName("gb2312");
                        String receivedMessage = String.valueOf(charset.decode(byteBuffer).array());
                        System.out.println(socketChannel.getLocalAddress() + "：" +receivedMessage);

                        clientMap.forEach((key,client) -> {
                            if (client == socketChannel) {
                                return;
                            }
                            byteBuffer.clear();
                            byteBuffer.put(charset.encode(key + ":" + receivedMessage));
                            byteBuffer.flip();

                            try {
                                client.write(byteBuffer);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                    }

                    selectionKeyIterator.remove();
                }
            }
        }
    }
}
